/*
 * author M.Chang
 *
 * Copyright 2008 Ph.Bonnet and M.Chang
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

#include "Mote.h"


/*****************************************************************************/

/* constructor */
Mote::Mote(std::string label)
{
  mote_id = label;
  epoch = 0;
  energy_constraint = 0;
  sensor_sparseness = 0;
}


/* destructor */
Mote::~Mote()
{
//  std::cout << "Mote destructor called" << std::endl;

/*
  std::vector<DataSet*>::iterator events_it = events.begin();

  for ( events_it++;
        events_it != events.end();
        events_it++)
  {
    delete *events_it;
  }
*/
}


/*****************************************************************************/

/*
  tokens_map["__domain__"] = "[| 1, 2, 3 | 1, 2, 3 | 1, 2, 3 |]";
  tokens_map["__reward_table__"] = "[| 10, 100, 21 | 100, 20, 21 | 100, 20, 21 |]";
  tokens_map["__energy_table__"] = "[| 1, 1, 1 | 1, 1, 1 | 1, 1, 1 |]";
  tokens_map["__time_table__"] = "[| 1, 1, 1 | 1, 1, 1 | 1, 1, 1 |]";
  tokens_map["__frequency_group__"] = "[| {1, 3}, {2, 4}, {} | {1, 3}, {2, 4}, {} | {1, 3}, {2, 4}, {} |]";
*/
void Mote::getEventMap(std::map<std::string,std::string>& tokens_map)
{
  int group_id = 1;
  std::stringstream ss;
  std::set<int> domain_set, frequency_domain_set;

//  domain_set.insert(0);
//  frequency_domain_set.insert(0);

  std::string domain, reward, energy, time, transmit, bandwidth, neighbor_energy, neighbor_time, frequency, group;

  domain.append("[");
  reward.append("[");
  energy.append("[");
  time.append("[");
  transmit.append("[");
  bandwidth.append("[");
  neighbor_energy.append("[");
  neighbor_time.append("[");
  frequency.append("[");
  group.append("[");

  std::string domain_buffer, reward_buffer, energy_buffer, time_buffer, transmit_buffer, bandwidth_buffer, neighbor_energy_buffer, neighbor_time_buffer, frequency_buffer;

  std::vector<DataSet>::iterator events_it = events.begin();
  events_it->getSet(domain_buffer, reward_buffer, energy_buffer, time_buffer, transmit_buffer, bandwidth_buffer, neighbor_energy_buffer, neighbor_time_buffer, frequency_buffer);
  events_it->getDomain(domain_set);
  events_it->getFrequencyDomain(frequency_domain_set);
  int number_of_sensors = events_it->getSize();
  int max_reward = events_it->getTotalReward();
  int max_energy = events_it->getTotalEnergy();
  int max_time = events_it->getTotalTime();

  domain.append(domain_buffer);
  reward.append(reward_buffer);
  energy.append(energy_buffer);
  time.append(time_buffer);
  transmit.append(transmit_buffer);
  bandwidth.append(bandwidth_buffer);
  neighbor_energy.append(neighbor_energy_buffer);
  neighbor_time.append(neighbor_time_buffer);
  frequency.append(frequency_buffer);

  ss.str("");
  ss << group_id++;
  group.append(ss.str());
  for (int i = 1; i < events_it->getSize(); i++)
  {
    group.append(", ");
    group.append(ss.str());
  }

  for ( events_it++;
        events_it < events.end();
        events_it++)
  {
    events_it->getSet(domain_buffer, reward_buffer, energy_buffer, time_buffer, transmit_buffer, bandwidth_buffer, neighbor_energy_buffer, neighbor_time_buffer, frequency_buffer);
    events_it->getDomain(domain_set);
    events_it->getFrequencyDomain(frequency_domain_set);
    number_of_sensors += events_it->getSize();
    max_reward += events_it->getTotalReward();
    max_energy += events_it->getTotalEnergy();
    max_time += events_it->getTotalTime();

    domain.append(", ");
    domain.append(domain_buffer);

    reward.append(", ");
    reward.append(reward_buffer);

    energy.append(", ");
    energy.append(energy_buffer);

    time.append(", ");
    time.append(time_buffer);

    transmit.append(", ");
    transmit.append(transmit_buffer);

    bandwidth.append(", ");
    bandwidth.append(bandwidth_buffer);

    neighbor_energy.append(", ");
    neighbor_energy.append(neighbor_energy_buffer);

    neighbor_time.append(", ");
    neighbor_time.append(neighbor_time_buffer);

    frequency.append(", ");
    frequency.append(frequency_buffer);

    ss.str("");
    ss << group_id++;
    group.append(", ");
    group.append(ss.str());
    for (int i = 1; i < events_it->getSize(); i++)
    {
      group.append(", ");
      group.append(ss.str());
    }
  }

  domain.append(" ]");
  reward.append(" ]");
  energy.append(" ]");
  time.append(" ]");
  transmit.append(" ]");
  bandwidth.append(" ]");
  neighbor_energy.append(" ]");
  neighbor_time.append(" ]");
  frequency.append(" ]");
  group.append(" ]");

  tokens_map["__mote_id__"] = mote_id;
  tokens_map["__domain__"] = domain;
  tokens_map["__reward_table__"] = reward;
  tokens_map["__energy_table__"] = energy;
  tokens_map["__time_table__"] = time;
  tokens_map["__transmit_table__"] = transmit;
  tokens_map["__bandwidth_table__"] = bandwidth;
  tokens_map["__neighbor_energy_table__"] = neighbor_energy;
  tokens_map["__neighbor_time_table__"] = neighbor_time;
  tokens_map["__frequency_table__"] = frequency;
  tokens_map["__group__"] = group;


  /* number of groups */
  ss.str("");
  ss << events.size();
  tokens_map["__number_of_groups__"] = ss.str();


  /* number of sensors */
  ss.str("");
  ss << number_of_sensors;
  tokens_map["__number_of_sensors__"] = ss.str();


  /* max reward times max frequency */
  ss.str("");
  ss << 2 * max_reward * (*frequency_domain_set.rbegin());
  tokens_map["__max_node_reward__"] = ss.str();

  /* max energy times max frequency */
  ss.str("");
  ss << max_energy * (*frequency_domain_set.rbegin());
  tokens_map["__max_node_energy__"] = ss.str();

  /* max time times max frequency */
  ss.str("");
  ss << max_time * (*frequency_domain_set.rbegin());
  tokens_map["__max_node_time__"] = ss.str();

  /* domain set */
  ss.str("");
  std::set<int>::iterator domain_set_it = domain_set.begin();
  ss << "{ " << *domain_set_it;

  if (domain_set_it != domain_set.end())
  {
    for ( domain_set_it++;
          domain_set_it != domain_set.end();
          domain_set_it++)
    {
      ss << ", ";
      ss << *domain_set_it;
    }
  }

  ss << "}";
  tokens_map["__domain_set__"] = ss.str();


  /* frequency domain set */
  ss.str("");
  std::set<int>::iterator frequency_domain_set_it = frequency_domain_set.begin();
  ss << "{ " << *frequency_domain_set_it;
  if (frequency_domain_set_it != frequency_domain_set.end())
  {
    for ( frequency_domain_set_it++;
          frequency_domain_set_it != frequency_domain_set.end();
          frequency_domain_set_it++)
    {
      ss << ", ";
      ss << *frequency_domain_set_it;
    }
  }
  ss << "}";
  tokens_map["__frequency_domain_set__"] = ss.str();


  /* energy constraint */
  ss.str("");
  ss << energy_constraint;
  tokens_map["__energy_constraint__"] = ss.str();

  /* time constraint */
  ss.str("");
  ss << epoch;
  tokens_map["__time_constraint__"] = ss.str();

  /* sensor sparseness */
  ss.str("");
  ss << sensor_sparseness;
  tokens_map["__sensor_sparseness__"] = ss.str();

}

void Mote::addDataSet(DataSet& DataSet)
{
  if (!DataSet.empty())
    events.push_back(DataSet);
}

/*****************************************************************************/

bool Mote::empty()
{
  if (events.empty())
    return true;
  else
    return false;
}

void Mote::setEpoch(unsigned int ep)
{
  epoch = ep;
}

void Mote::setEnergy(unsigned int en)
{
  energy_constraint = en;
}

void Mote::setSensorSparseness(unsigned int se)
{
  sensor_sparseness = se;
}

void Mote::getName(std::string& name)
{
  name = mote_id;
}

/*****************************************************************************/

std::string Mote::toString()
{
  std::string output;
  std::map<std::string,std::string> tokens_map;

  Mote::getEventMap(tokens_map);

  std::map<std::string,std::string>::iterator tokens_map_it;

  for (tokens_map_it = tokens_map.begin();
       tokens_map_it != tokens_map.end();
       tokens_map_it++)
  {
    output.append(tokens_map_it->first);
    output.append(": ");
    output.append(tokens_map_it->second);
    output.append("\n");
  }

  return output;
}


